/*
 * Copyright 2008 Zoundry LLC, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package org.zoundry.gaedt.ui.editors.operations;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.AbstractOperation;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.zoundry.gaedt.core.util.ZGaeUtil;


/**
 * An operation implementation that knows how to set a JavaBean property value.
 */
public class ZGaeSetBeanPropertyOperation extends AbstractOperation implements IZGaeUndoableOperation
{
    /** The bean to modify. */
    private Object mBean;
    /** The bean property name. */
    private String mPropertyName;
    /** The new value of the bean property. */
    private Object mNewValue;
    /** The UI updater. */
    private IZGaeUIUpdater mUIUpdater;

    /** The original value of the bean property. */
    private Object mOriginalValue;

    /**
     * C'tor.
     *
     * @param aBean
     * @param aPropertyName
     * @param aNewValue
     * @param aLabel
     * @param aUIUpdater
     */
    public ZGaeSetBeanPropertyOperation(Object aBean, String aPropertyName, Object aNewValue, String aLabel,
            IZGaeUIUpdater aUIUpdater)
    {
        super(aLabel);
        setBean(aBean);
        setPropertyName(aPropertyName);
        setNewValue(aNewValue);
        setUIUpdater(aUIUpdater);
    }

    /**
     * @see org.zoundry.gaedt.ui.editors.operations.IZGaeUndoableOperation#shouldExecute()
     */
    public boolean shouldExecute()
    {
        try
        {
            Object originalValue = getOriginalValue();
            return originalValue != getNewValue() && !originalValue.equals(getNewValue());
        }
        catch (Exception e)
        {
            ZGaeUtil.logError(e);
        }
        return false;
    }

    /**
     * @see org.eclipse.core.commands.operations.AbstractOperation#execute(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.core.runtime.IAdaptable)
     */
    @Override
    public IStatus execute(IProgressMonitor aMonitor, IAdaptable aInfo) throws ExecutionException
    {
        try
        {
            BeanUtils.setProperty(getBean(), getPropertyName(), getNewValue());
            getUIUpdater().updateUIForExecute(getNewValue());
        }
        catch (Exception e)
        {
            ZGaeUtil.logError(e);
        }
        return Status.OK_STATUS;
    }

    /**
     * @see org.eclipse.core.commands.operations.AbstractOperation#redo(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.core.runtime.IAdaptable)
     */
    @Override
    public IStatus redo(IProgressMonitor aMonitor, IAdaptable aInfo) throws ExecutionException
    {
        try
        {
            BeanUtils.setProperty(getBean(), getPropertyName(), getNewValue());
            getUIUpdater().updateUIForRedo(getNewValue());
        }
        catch (Exception e)
        {
            ZGaeUtil.logError(e);
        }
        return Status.OK_STATUS;
    }

    /**
     * @see org.eclipse.core.commands.operations.AbstractOperation#undo(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.core.runtime.IAdaptable)
     */
    @Override
    public IStatus undo(IProgressMonitor aMonitor, IAdaptable aInfo) throws ExecutionException
    {
        try
        {
            BeanUtils.setProperty(getBean(), getPropertyName(), getOriginalValue());
            getUIUpdater().updateUIForUndo(getOriginalValue());
        }
        catch (Exception e)
        {
            ZGaeUtil.logError(e);
        }
        return Status.OK_STATUS;
    }

    /**
     * @return the bean
     */
    protected Object getBean()
    {
        return mBean;
    }

    /**
     * @param aBean the bean to set
     */
    protected void setBean(Object aBean)
    {
        mBean = aBean;
    }

    /**
     * @return the originalValue
     */
    protected Object getOriginalValue() throws Exception
    {
        if (mOriginalValue == null)
        {
            mOriginalValue = BeanUtilsBean.getInstance().getPropertyUtils().getProperty(getBean(), getPropertyName());
        }
        return mOriginalValue;
    }

    /**
     * @param aOriginalValue the originalValue to set
     */
    protected void setOriginalValue(Object aOriginalValue)
    {
        mOriginalValue = aOriginalValue;
    }

    /**
     * @return the newValue
     */
    protected Object getNewValue()
    {
        return mNewValue;
    }

    /**
     * @param aNewValue the newValue to set
     */
    protected void setNewValue(Object aNewValue)
    {
        mNewValue = aNewValue;
    }

    /**
     * @return the propertyName
     */
    protected String getPropertyName()
    {
        return mPropertyName;
    }

    /**
     * @param aPropertyName the propertyName to set
     */
    protected void setPropertyName(String aPropertyName)
    {
        mPropertyName = aPropertyName;
    }

    /**
     * @return the uIUpdater
     */
    protected IZGaeUIUpdater getUIUpdater()
    {
        return mUIUpdater;
    }

    /**
     * @param aUpdater the uIUpdater to set
     */
    protected void setUIUpdater(IZGaeUIUpdater aUpdater)
    {
        mUIUpdater = aUpdater;
    }
}
